package com.youhome.service.service.impl;

import com.aliyun.oss.OSSClient;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.youhome.common.exception.CustomException;
import com.youhome.common.queue.QueueList;
import com.youhome.common.config.ReportOSSConfig;
import com.youhome.common.response.Result;
import com.youhome.common.response.ResultCode;
import com.youhome.service.mapper.ReportMapper;
import com.youhome.service.model.BUser;
import com.youhome.service.model.ListHub;
import com.youhome.service.model.Principal;
import com.youhome.service.model.Report;
import com.youhome.service.service.BUserService;
import com.youhome.service.service.ListHubService;
import com.youhome.service.service.OSSService;
import com.youhome.service.service.ReportService;
import com.youhome.utils.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.io.*;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * Created by chen365 on 2017/9/11.
 */
@Service
public class ReportServiceImpl implements ReportService {
    @Autowired
    private ReportMapper reportMapper;
    @Autowired
    private ReportOSSConfig ossConfig;
    @Autowired
    private BUserService bUserService;
    @Autowired
    private OSSService ossService;
    @Autowired
    private ListHubService listHubService;

    @Override
    @Transactional
    public int insertSelective(Report record) throws Exception {
        int success = reportMapper.insertSelective(record);
        //扣除下载份数
        if (record.getId() > 0 && record.getType() == 1) {
            bUserService.updateReportCount(-1, record.getUserId());
        }
        return success;
    }

    @Override
    public Report selectByPrimaryKey(Long id) throws Exception {
        return reportMapper.selectByPrimaryKey(id);
    }

    @Override
    public int updateByPrimaryKeySelective(Report record) throws Exception {
        return reportMapper.updateByPrimaryKeySelective(record);
    }

    @Override
    public PageInfo<Report> selectByUserId(Long houseId, int page) throws Exception {
        PageHelper.startPage(page, 10);
        List<Report> list = reportMapper.selectByUserId(houseId);
        return new PageInfo<>(list);
    }

    @Override
    public void createPDF() throws Exception {
        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
        scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
            public void run() {
                System.out.println(Thread.currentThread().getName() + "正在执行。。。");
                do {
                    //获取队列对像
                    Object obj = QueueList.getObject();
                    Report report = (Report) obj;
                    System.err.println(report.toString());
                    //生成PDF
                    createPDF(report);
                } while (QueueList.isQueueEmpty());
            }
        }, 1, 3, TimeUnit.SECONDS);
    }

    @Override
    public Report findByHouseIDAndUserIDAndType(String houseId, Long userId, Integer type) {
        Report report = new Report();
        report.setUserId(userId);
        report.setHouseId(houseId);
        report.setType(type);
        return reportMapper.selectByHouseIDAndUserIDAndType(report);
    }

    @Override
    public int updateStatus(Report record) throws Exception {
        return reportMapper.updateStatus(record);
    }

    public Boolean createPDF(Report report) {
        System.err.println("开始生成报告。。。");
        Boolean success = false;
        long start = System.currentTimeMillis();
        String sourceUrl = "";
        String targetPDF = "";
        String command = "";
        String targetMarkPDF = "";
        String markImage = "";
        String filename = UUID.randomUUID().toString().replace("-", "") + ".pdf";
        if (report.getType() == 0) {
            sourceUrl = "report/free/" + report.getHouseId();
        } else {
            sourceUrl = "report/charge/" + report.getHouseId();
        }

        String os = System.getProperty("os.name");
        System.err.println("os:" + os);
        if (os.toLowerCase().startsWith("win")) {
            sourceUrl = "http://localhost:9090/" + sourceUrl;
            targetPDF = "c:/out/report/" + report.getFile();
            targetMarkPDF = "c:/out/report/" + filename;
            markImage = "c:/out/report/logo.png";
            //command = "phantomjs C:/Java/tool/rasterize.js " + sourceUrl + " " + targetPDF + " 840px*24500px";
            command = "phantomjs C:/Java/tool/rasterize.js " + sourceUrl + " " + targetPDF;
        } else if (os.toLowerCase().startsWith("mac")) {
            sourceUrl = "http://localhost:9090/" + sourceUrl;
            targetPDF = "/data/report/" + report.getFile();
            targetMarkPDF = "/data/report/" + filename;
            markImage = "/data/report/logo.png";
            //command = "phantomjs /usr/local/phantomjs/examples/rasterize.js " + sourceUrl + " " + targetPDF + " 840px*24500px";
            command = "phantomjs /usr/local/phantomjs/examples/rasterize.js " + sourceUrl + " " + targetPDF;
        } else {
            sourceUrl = "http://localhost:8091/" + sourceUrl;
            targetPDF = "/data/report/" + report.getFile();
            targetMarkPDF = "/data/report/" + filename;
            markImage = "/data/report/logo.png";
            //command = "phantomjs /data/report/rasterize.js " + sourceUrl + " " + targetPDF + " 840px*24500px";
            command = "phantomjs /data/report/rasterize.js " + sourceUrl + " " + targetPDF;
        }

        System.err.println("command:" + command);
        try {
            Process p = Runtime.getRuntime().exec(command);
            InputStream is = p.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(is));
            String line;
            StringBuffer stringBuffer = new StringBuffer();
            while ((line = reader.readLine()) != null) {
                stringBuffer.append(line);
            }
            p.waitFor();
            is.close();
            reader.close();
            p.destroy();
            System.err.println(stringBuffer.toString());
            if (StringUtils.isEmpty(stringBuffer.toString())) {
                success = true;
                System.err.println("已生成报告。。。");
            } else {
                System.err.println("生成报告失败。。。");
            }

        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println((System.currentTimeMillis() - start) + " 毫秒");

        int status = 2;  //失败

        if (success) {
            //添加水印
            // if (new PDFUtil().addMark(targetPDF, targetMarkPDF, markImage)) {
            //report.setFile("report/" + filename); //修改文件名
            //uploadReport(targetMarkPDF);//上传oss
            //status = 1; //成功
            //}

            report.setFile("report/" + report.getFile()); //修改文件名
            uploadReport(targetPDF);//上传oss
            status = 1; //成功
        }
        report.setStatus(status);
        System.err.println(report.toString());
        reportMapper.updateStatus(report);
        return success;
    }

    /**
     * 上传 PDF到 OSS
     *
     * @param path
     */
    public void uploadReport(String path) {
        System.err.println("报告开始上传oss。。。");
        try {
            File file = new File(path);
            if (file.exists()) {
                OSSClient ossClient = new OSSClient(ossConfig.getEndpoint(), ossConfig.getAccessKeyId(), ossConfig.getAccessKeySecret());
                // 设置bucket权限
                //ossClient.setBucketAcl(ossConfig.getBacketName(), CannedAccessControlList.Private);
                String md5key = ossService.uploadObject2OSS(ossClient, file, ossConfig.getBacketName(), "report");
                //logger.info("上传后的文件MD5数字唯一签名:" + md5key);
                System.err.println("报告已经上传oss。。。");
                FileUtils.deleteFile(path); //上传成功后删除文件
                ossClient.shutdown();
            } else {
                System.err.println("文件不存在");
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("。。。。。。。。。上传系统错误。。。。。。。");
        }
    }

    @Override
    public String createTemporaryUrl(Long id) throws CustomException {
        BUser currentUser = bUserService.getCurrentUser();
        Report report = reportMapper.selectByPrimaryKey(id);
        if (report == null) {
            throw new CustomException(ResultCode.NOT_EXIST_REPORT);
        }
        System.err.println("user:==>>" + currentUser.getUserId() + "<<===report===>>" + report.getUserId());
        if (!currentUser.getUserId().equals(report.getUserId())) {
            throw new CustomException(ResultCode.ILLEGAL_REQUEST);
        }
        if (report.getStatus() != 1) {
            throw new CustomException(ResultCode.REPORT_NOT_GENERATED);
        }
        String filename = report.getFile();
        System.err.println("objectExist");

        OSSClient ossClient = new OSSClient(
                ossConfig.getEndpoint(),
                ossConfig.getAccessKeyId(),
                ossConfig.getAccessKeySecret());

        System.err.println("filename:" + filename);
        if (ossService.exist(ossClient, ossConfig.getBacketName(), filename)) {
            System.err.println("objectExist true");
            Long time = Long.valueOf(1800 * 1000);
            return ossService.createTemporaryUrl(ossConfig, filename, time);
        } else {
            System.err.println("objectExist false");
            return null;
        }
    }

    @Override
    public Boolean selectExist(Integer type, String houseId) throws CustomException {
        BUser currentUser = bUserService.getCurrentUser();
        if (currentUser == null) {
            throw new CustomException(ResultCode.EXPIRED_LOGIN);
        }
        ListHub listHub = listHubService.selectByPrimaryKey(houseId);
        if (listHub == null) {
            throw new CustomException(ResultCode.HOUSE_INEXISTENCE);
        }
        if (type != 0 && type != 1) {
            throw new CustomException(ResultCode.ERROR_REPORT_TYPE);
        }
        Report report = findByHouseIDAndUserIDAndType(houseId, currentUser.getUserId(), type);
        if (report == null) {
            System.err.println("报告未生成过");
            return true;
            //throw new CustomException(ResultCode.REPORT_NOT_GENERATE);
        }
        if (report.getStatus() == 0) {
            //正在生成
            System.err.println("报告正在生成");
            throw new CustomException(ResultCode.REPORT_HAS_BEEN_GENERATED);
        } else if (report.getStatus() == 1) {
            //生成成功
            System.err.println("报告生成成功");
            throw new CustomException(ResultCode.REPORT_HAS_GENERATED);
        } else if (report.getStatus() == 2) {
            //生成失败
            System.err.println("报告生成失败");
            throw new CustomException(ResultCode.REPORT_GENERATE_FAILURE);
        }

        return true;
    }

    @Override
    public Report generate(Integer type, String houseId) throws CustomException {

        try {
            if (StringUtils.isEmpty(houseId)) {
                throw new CustomException(ResultCode.EMPTY_PARAM);
            }
            if (StringUtils.isEmpty(type)) {
                throw new CustomException(ResultCode.EMPTY_PARAM);
            }
            BUser currentUser = bUserService.getCurrentUser();
            if (currentUser == null) {
                throw new CustomException(ResultCode.EXPIRED_LOGIN);
            }
            ListHub listHub = listHubService.selectByPrimaryKey(houseId);
            if (listHub == null) {
                throw new CustomException(ResultCode.HOUSE_INEXISTENCE);
            }
            String zip = listHub.getZip();

            if (StringUtils.isEmpty(zip))
                throw new CustomException(ResultCode.EMPTY_ZIP);

            if (type != 0 && type != 1) {
                throw new CustomException(ResultCode.ERROR_REPORT_TYPE);
            }
//            if (reportService.findByHouseIDAndUserIDAndType(houseId, currentUser.getUserId(), type) != null)
//                throw new CustomException(ResultCode.REPORT_HAS_BEEN_GENERATED);


            Report report2 = findByHouseIDAndUserIDAndType(houseId, currentUser.getUserId(), type);
            if (report2 != null) {
                if (report2.getStatus() == 0) {
                    //正在生成
                    throw new CustomException(ResultCode.REPORT_HAS_BEEN_GENERATED);
                } else if (report2.getStatus() == 1) {
                    //生成成功
                    throw new CustomException(ResultCode.REPORT_HAS_GENERATED);
                }
            }

            int reportCount = bUserService.findRepotCountById(currentUser.getUserId());

            //收费报告
            if (type == 1) {
                if (reportCount < 1) {
                    throw new CustomException(ResultCode.REPORT_COUNT_INSUFFICIENT);
                }
            }

            System.err.println("reportCount:" + reportCount);

            String file = UUID.randomUUID().toString().replace("-", "") + ".pdf";
            Report report = new Report();
            report.setHouseId(listHub.getHouseId());
            String fullAddress = listHub.getAddress();
            report.setTitle(fullAddress);
            report.setZipcode(listHub.getZip());
            report.setFile(file);
            report.setUserId(currentUser.getUserId());
            report.setType(type);
            report.setStatus(0); //未生成
            report.setCreated(new Date());

            insertSelective(report);

            LinkedList<Object> linkedList = new LinkedList<>();
            linkedList.add(report);
            QueueList.pushListObject(linkedList);
            createPDF();
            return report;
        } catch (Exception e) {
            e.printStackTrace();
            throw new CustomException(ResultCode.ERROR);
        }
    }

    @Override
    public PageInfo<Report> selectByPage(Principal principal, Integer pageNumber, Integer pageSize) throws CustomException {
        if (StringUtils.isEmpty(pageNumber) || pageNumber < 1) {
            pageNumber = 1;
        }
        if (StringUtils.isEmpty(pageSize) || pageSize < 1) {
            pageSize = 10;
        }
        Long userId = principal.getUser().getUserId();
        PageHelper.startPage(pageNumber, pageSize);
        List<Report> list = reportMapper.selectByUserId(userId);
        return new PageInfo<>(list);


    }

}
